#ifndef ADAMS_BASHFORTH_HPP
#define ADAMS_BASHFORTH_HPP

#include "AdamsBashforthCoeff.hpp"
#include "LMM.hpp"
#include <cmath>
#include <iostream>

class AdamsBashforth : public LMM {
public:
  AdamsBashforth(int dim, double dt, double t0, double t1, int p)
      : LMM(dim, dt, t0, t1, p) {
    if (p > IntScheme::ABCoeff::maxP || p < IntScheme::ABCoeff::minP) {
      std::cerr << "Invalid p" << std::endl;
    }
    m_s = IntScheme::ABCoeff::s[p - IntScheme::ABCoeff::minP];
    m_u.resize(std::floor((m_t1 - m_t0) / dt) + 1, m_dim);
    m_u.setZero();
  }

  const std::vector<double> getAlpha() const {
    int idx = IntScheme::ABCoeff::offset[m_p - IntScheme::ABCoeff::minP];
    return std::vector<double>(IntScheme::ABCoeff::alpha.begin() + idx,
                               IntScheme::ABCoeff::alpha.begin() + idx + m_s +
                                   1);
  }
  const std::vector<double> getBeta() const {
    int idx = IntScheme::ABCoeff::offset[m_p - IntScheme::ABCoeff::minP];
    return std::vector<double>(IntScheme::ABCoeff::beta.begin() + idx,
                               IntScheme::ABCoeff::beta.begin() + idx + m_s +
                                   1);
  }

  int getS() const { return m_s; }
  
  Eigen::MatrixXd getU() const { return m_u; }
};

#endif // ADAMS_BASHFORTH_HPP